/**
 @author        Groupe de PDP
 @date          19/02/2009 (last modified)
 @version       1.0

 @code          Fenêtre principale de l'application
 @class         MainWindow
*/

#include <QtGui>

#include "mainwindow.h"
#include "diagramitem.h"
#include "diagramscene.h"
// #include "diagramtextitem.h"

const int InsertTextButton = 10;

MainWindow::MainWindow()
{
    // actions
    createActions();

    // menus
    createMenus();

    // boite à outils
    createToolBox();

    // paneau de dessin du graphe
    scene = new DiagramScene(graphMenu); // Le nom va changer : GraphScene probablement

    // dimension du paneau graphe
    scene->setSceneRect(QRectF(0, 0, 5000, 5000));

    // Devra changer : connect de création des éléments du graphe
    connect(scene, SIGNAL(itemInserted(DiagramItem *)),
             this, SLOT(itemInserted(DiagramItem *)));

    connect(scene, SIGNAL(textInserted(QGraphicsTextItem *)),
         this, SLOT(textInserted(QGraphicsTextItem *)));

    connect(scene, SIGNAL(itemSelected(QGraphicsItem *)),
         this, SLOT(itemSelected(QGraphicsItem *)));

    // création des barres d'outils
    createToolbars();

    QHBoxLayout * layout = new QHBoxLayout;

    graphView = new QGraphicsView(scene);
    layout->addWidget(graphView);

    QWidget *widget = new QWidget;
    widget->setLayout(layout);

    setCentralWidget(widget);

    // Création des boîtes de dialogue
    dialogNewProject = new newProjectConfigDialog(this);
    connect(dialogNewProject, SIGNAL(create(QString)), this, SLOT(launchNewProject(QString)));

    // Possibilité d'afficher les boîtes à outils en barre vertical à gauche
    this->setDockOptions(QMainWindow::VerticalTabs);

    // Interface en multifenêtre au lancement
    undockWindowAction->setEnabled(false);

    setWindowTitle(tr("Software Analysis Tool"));
}

/*---------------------------*/
/*      SLOTS PRIVES         */
/*---------------------------*/

void
MainWindow::newProjectWindow()
{
    dialogNewProject->setModal(true);
    dialogNewProject->show();
}

void
MainWindow::launchNewProject(QString projectPath)
{
    // Chargement du projet : Partie à Guillaume
}

void
MainWindow::openProjectWindow()
{
    // to do later
}

void
MainWindow::saveProjectWindow()
{
    // to do later
}

void
MainWindow::dockWindow()
{
    dock->setFloating(false);
    dock2->setFloating(false);
    undockWindowAction->setEnabled(true);
    dockWindowAction->setEnabled(false);
}

void
MainWindow::undockWindow()
{
    dock->setFloating(true);
    dock2->setFloating(true);
    dockWindowAction->setEnabled(true);
    undockWindowAction->setEnabled(false);
}

void
MainWindow::increaseZoom()
{

}

void
MainWindow::decreaseZoom()
{

}


void MainWindow::backgroundButtonGroupClicked(QAbstractButton *button)
{
   /*  QList<QAbstractButton *> buttons = backgroundButtonGroup->buttons();
     foreach (QAbstractButton *myButton, buttons) {
     if (myButton != button)
         button->setChecked(false);
     }
     QString text = button->text();
     if (text == tr("Blue Grid"))
         scene->setBackgroundBrush(QPixmap(":/images/background1.png"));
     else if (text == tr("White Grid"))
         scene->setBackgroundBrush(QPixmap(":/images/background2.png"));
     else if (text == tr("Gray Grid"))
         scene->setBackgroundBrush(QPixmap(":/images/background3.png"));
     else
         scene->setBackgroundBrush(QPixmap(":/images/background4.png"));

     scene->update();
     view->update();*/
 }

 void MainWindow::buttonGroupClicked(int id)
 {
     QList<QAbstractButton *> buttons = buttonGroup->buttons();
     foreach (QAbstractButton *button, buttons) {
     if (buttonGroup->button(id) != button)
         button->setChecked(false);
     }
     if (id == InsertTextButton) {
         scene->setMode(DiagramScene::InsertText);
     } else {
         scene->setItemType(DiagramItem::DiagramType(id));
         scene->setMode(DiagramScene::InsertItem);
     }
 }

/*
 void MainWindow::deleteItem()
 {
     foreach (QGraphicsItem *item, scene->selectedItems()) {
         if (item->type() == DiagramItem::Type) {
             qgraphicsitem_cast<DiagramItem *>(item)->removeArrows();
         }
         scene->removeItem(item);
     }
 }
*/

 void MainWindow::pointerGroupClicked(int)
 {
     scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId()));
 }

 void MainWindow::itemInserted(DiagramItem *item)
 {
     scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId()));
     buttonGroup->button(int(item->diagramType()))->setChecked(false);
 }

 void MainWindow::textInserted(QGraphicsTextItem *)
 {
     buttonGroup->button(InsertTextButton)->setChecked(false);
     scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId()));
 }

/*
 void MainWindow::currentFontChanged(const QFont &)
 {
     handleFontChange();
 }

 void MainWindow::fontSizeChanged(const QString &)
 {
     handleFontChange();
 }
*/

void
MainWindow::sceneScaleChanged(const QString &scale)
{
    double newScale = scale.left(scale.indexOf(tr("%"))).toDouble() / 100.0;
    QMatrix oldMatrix = graphView->matrix();
    graphView->resetMatrix();
    graphView->translate(oldMatrix.dx(), oldMatrix.dy());
    graphView->scale(newScale, newScale);
}

void
MainWindow::sceneScaleIncreased()
{
    QMatrix oldMatrix = graphView->matrix();
    graphView->resetMatrix();
    graphView->translate(oldMatrix.dx(), oldMatrix.dy());
    graphView->scale(0.25, 0.25);
}

void
MainWindow::sceneScaleDecreased()
{
    QMatrix oldMatrix = graphView->matrix();
    graphView->resetMatrix();
    graphView->translate(oldMatrix.dx(), oldMatrix.dy());
    graphView->scale(1.25, 1.25);
}

 void MainWindow::textColorChanged()
 {
     textAction = qobject_cast<QAction *>(sender());
     fontColorToolButton->setIcon(createColorToolButtonIcon(
                 ":pointeur.png",
                 qVariantValue<QColor>(textAction->data())));
     textButtonTriggered();
 }

 void MainWindow::itemColorChanged()
 {
     fillAction = qobject_cast<QAction *>(sender());
     fillColorToolButton->setIcon(createColorToolButtonIcon(
                  ":/images/floodfill.png",
                  qVariantValue<QColor>(fillAction->data())));
     fillButtonTriggered();
 }

 void MainWindow::lineColorChanged()
 {
     lineAction = qobject_cast<QAction *>(sender());
     lineColorToolButton->setIcon(createColorToolButtonIcon(
                  ":/images/linecolor.png",
                  qVariantValue<QColor>(lineAction->data())));
     lineButtonTriggered();
 }

 void MainWindow::textButtonTriggered()
 {
     scene->setTextColor(qVariantValue<QColor>(textAction->data()));
 }

 void MainWindow::fillButtonTriggered()
 {
     scene->setItemColor(qVariantValue<QColor>(fillAction->data()));
 }

 void MainWindow::lineButtonTriggered()
 {
     scene->setLineColor(qVariantValue<QColor>(lineAction->data()));
 }

 void MainWindow::handleFontChange()
 {
     QFont font = fontCombo->currentFont();
     font.setPointSize(fontSizeCombo->currentText().toInt());
     font.setWeight(boldAction->isChecked() ? QFont::Bold : QFont::Normal);
     font.setItalic(italicAction->isChecked());
     font.setUnderline(underlineAction->isChecked());

     scene->setFont(font);
 }

 void MainWindow::itemSelected(QGraphicsItem *item)
 {
    // DiagramTextItem *textItem =
    // qgraphicsitem_cast<DiagramTextItem *>(item);

   //  QFont font = textItem->font();
   //  QColor color = textItem->defaultTextColor();
//     fontCombo->setCurrentFont(font);
 //    fontSizeCombo->setEditText(QString().setNum(font.pointSize()));
  //   boldAction->setChecked(font.weight() == QFont::Bold);
  //   italicAction->setChecked(font.italic());
  //   underlineAction->setChecked(font.underline());
 }

void
MainWindow::about()
{
    QMessageBox::about(this, tr("About Diagram Scene"),
                       tr("The <b>Diagram Scene</b> example shows "
                          "use of the graphics framework."));
}

void
MainWindow::help()
{
    QMessageBox::about(	this, tr("SAT Help"), tr("Help coming soon."));
}

void
MainWindow::createToolBox()
{
    dock = new QDockWidget(tr("Tree files"), this);
    dock->setAllowedAreas(Qt::LeftDockWidgetArea);
    //dock->setFeatures(QDockWidget::DockWidgetVerticalTitleBar);

    tree = new TreeFiles(dock);
    dock->setWidget(tree);

    addDockWidget(Qt::LeftDockWidgetArea, dock);
    viewMenu->addAction(dock->toggleViewAction());
    dock->setFloating(true);
    dock->setAllowedAreas(Qt::AllDockWidgetAreas);
    dock->setGeometry (10, 100, 230, 300);

    dock2 = new QDockWidget(tr("Metrics"), this);
    dock2->setAllowedAreas(Qt::LeftDockWidgetArea);
    metricsList = new QListWidget(dock2);
    metricsList->addItems(QStringList()
         << "Metric 1"
         << "Metric 2"
         << "Metric 3"
         << "Metric 4"
         << "Metric 5");
    dock2->setWidget(metricsList);
    addDockWidget(Qt::LeftDockWidgetArea, dock2);
    viewMenu->addAction(dock2->toggleViewAction());
    dock2->setFloating(true);
    dock2->setAllowedAreas(Qt::AllDockWidgetAreas);
    dock2->setGeometry (10, 410, 230, 300);
}

void
MainWindow::createActions()
{
     newProjectAction = new QAction(tr("&New project"), this);
     newProjectAction->setShortcut(tr("Ctrl+W"));
     newProjectAction->setStatusTip(tr("Create a new analysis project"));
     connect(newProjectAction, SIGNAL(triggered()), this, SLOT(newProjectWindow()));

     openProjectAction = new QAction(tr("&Open project"), this);
     openProjectAction->setShortcut(tr("Ctrl+P"));
     openProjectAction->setStatusTip(tr("Open an existing project"));
     connect(openProjectAction, SIGNAL(triggered()), this, SLOT(openProjectWindow()));

     saveProjectAction = new QAction(tr("&Save project"), this);
     saveProjectAction->setShortcut(tr("Ctrl+S"));
     saveProjectAction->setStatusTip(tr("Save current project"));
     connect(openProjectAction, SIGNAL(triggered()), this, SLOT(saveProjectWindow()));

     exitAction = new QAction(tr("E&xit"), this);
     exitAction->setShortcut(tr("Ctrl+X"));
     exitAction->setStatusTip(tr("Quit SAT application"));
     connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));

     /* action view */
     dockWindowAction = new QAction(tr("&Dock windows"), this);
     dockWindowAction->setShortcut(tr("Ctrl+D"));
     dockWindowAction->setStatusTip(tr("Dock windows into a single window"));
     connect(dockWindowAction, SIGNAL(triggered()), this, SLOT(dockWindow()));

     undockWindowAction = new QAction(tr("&Undock window"), this);
     undockWindowAction->setShortcut(tr("Ctrl+U"));
     undockWindowAction->setStatusTip(tr("Undock window into multiple top-level windows"));
     connect(undockWindowAction, SIGNAL(triggered()), this, SLOT(undockWindow()));


     /* actions Graph */
     increaseZoomAction = new QAction(QIcon(":loupe_plus.png"),
                                tr("Zoom &+"), this);
     increaseZoomAction->setShortcut(tr("Ctrl++"));
     increaseZoomAction->setStatusTip(tr("Increase zoom view"));
     connect(increaseZoomAction, SIGNAL(triggered()), this, SLOT(sceneScaleIncreased()));

     decreaseZoomAction = new QAction(QIcon(":loupe_moins.png"),
                                tr("Zoom &-"), this);
     decreaseZoomAction->setShortcut(tr("Ctrl+-"));
     decreaseZoomAction->setStatusTip(tr("Decrease zoom view"));
     connect(decreaseZoomAction, SIGNAL(triggered()), this, SLOT(sceneScaleDecreased()));

     graphOptionsAction = new QAction(tr("Gra&ph Options"), this);
     graphOptionsAction->setShortcut(tr("Ctrl+P"));
     connect(graphOptionsAction, SIGNAL(triggered()), this, SLOT(help()));

     /* actions Analysis */
     makeAnalysisAction = new QAction(tr("&Make"), this);
     makeAnalysisAction->setShortcut(tr("Alt+F9"));
     connect(makeAnalysisAction, SIGNAL(triggered()), this, SLOT(help()));

     viewGraphAction = new QAction(tr("&View graph"), this);
     viewGraphAction->setShortcut(tr("Alt+F10"));
     connect(viewGraphAction, SIGNAL(triggered()), this, SLOT(help()));

     analysisPropertiesAction = new QAction(tr("&Properties"), this);
     analysisPropertiesAction->setShortcut(tr("Ctrl+P"));
     connect(analysisPropertiesAction, SIGNAL(triggered()), this, SLOT(help()));

    /* action Help */
    aboutAction = new QAction(tr("A&bout"), this);
    aboutAction->setShortcut(tr("Ctrl+B"));
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(help()));
}

void MainWindow::createMenus()
{
    // Menu " File "
    fileMenu = menuBar()->addMenu(tr("&File"));
    fileMenu->addAction(newProjectAction);
    fileMenu->addSeparator();
    fileMenu->addAction(openProjectAction);
    fileMenu->addAction(saveProjectAction);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAction);

    // Menu " View "
    viewMenu = menuBar()->addMenu(tr("&View"));
    viewMenu->addAction(dockWindowAction);
    viewMenu->addAction(undockWindowAction);
    viewMenu->addSeparator();
    toolbarMenu = viewMenu->addMenu(tr("&Tool bars"));
    viewMenu->addSeparator();

    // Menu " Graph "
    graphMenu = menuBar()->addMenu(tr("&Graph"));
    graphMenu->addAction(increaseZoomAction);
    graphMenu->addAction(decreaseZoomAction);
    graphMenu->addSeparator();
    graphMenu->addAction(graphOptionsAction);

    // Menu " Analysis "
    analysisMenu = menuBar()->addMenu(tr("&Analysis"));
    analysisMenu->addAction(makeAnalysisAction);
    analysisMenu->addAction(viewGraphAction);
    analysisMenu->addSeparator();
    analysisMenu->addAction(analysisPropertiesAction);

    // Menu " Help "
    helpMenu = menuBar()->addMenu(tr("&Help"));
    helpMenu->addAction(aboutAction);

}

 void MainWindow::createToolbars()
 {
     /* -- View Edit toolbar -- */
     graphViewToolBar = addToolBar(tr("Edit view"));

     graphScaleCombo = new QComboBox;
     QStringList scales;
     scales << tr("50%") << tr("75%") << tr("100%") << tr("125%") << tr("150%");
     graphScaleCombo->addItems(scales);
     graphScaleCombo->setCurrentIndex(2); // 100% par défaut
     connect(graphScaleCombo, SIGNAL(currentIndexChanged(const QString &)),
             this, SLOT(sceneScaleChanged(const QString &)));

     graphViewToolBar->addAction(increaseZoomAction);
     graphViewToolBar->addAction(decreaseZoomAction);
     graphViewToolBar->addWidget(graphScaleCombo);

     toolbarMenu->addAction(graphViewToolBar->toggleViewAction());

     /* -- Graph Edit toolbar -- */
     graphEditToolBar = addToolBar(tr("Edit graph"));
     // nodes pointer
     QToolButton * pointerButton = new QToolButton;
     pointerButton->setCheckable(true);
     pointerButton->setChecked(true);
     pointerButton->setIcon(QIcon(":pointeur.jpg"));

     graphEditToolBar->addWidget(pointerButton);

     // Change nodes color button
     fillColorToolButton = new QToolButton;
     fillColorToolButton->setPopupMode(QToolButton::MenuButtonPopup);
     fillColorToolButton->setMenu(createColorMenu(SLOT(itemColorChanged()),
                          Qt::white));
     fillAction = fillColorToolButton->menu()->defaultAction();
     fillColorToolButton->setIcon(createColorToolButtonIcon(
     ":/images/floodfill.png", Qt::white));
     connect(fillColorToolButton, SIGNAL(clicked()),
             this, SLOT(fillButtonTriggered()));

     lineColorToolButton = new QToolButton;
     lineColorToolButton->setPopupMode(QToolButton::MenuButtonPopup);
     lineColorToolButton->setMenu(createColorMenu(SLOT(lineColorChanged()),
                                  Qt::black));
     lineAction = lineColorToolButton->menu()->defaultAction();
     lineColorToolButton->setIcon(createColorToolButtonIcon(
         ":/images/linecolor.png", Qt::black));
     connect(lineColorToolButton, SIGNAL(clicked()),
             this, SLOT(lineButtonTriggered()));

     graphEditToolBar->addWidget(fillColorToolButton);
     graphEditToolBar->addWidget(lineColorToolButton);

     toolbarMenu->addAction(graphEditToolBar->toggleViewAction());
}

 QWidget *MainWindow::createBackgroundCellWidget(const QString &text,
                         const QString &image)
 {
     QToolButton *button = new QToolButton;
     button->setText(text);
     button->setIcon(QIcon(image));
     button->setIconSize(QSize(50, 50));
     button->setCheckable(true);
     backgroundButtonGroup->addButton(button);

     QGridLayout *layout = new QGridLayout;
     layout->addWidget(button, 0, 0, Qt::AlignHCenter);
     layout->addWidget(new QLabel(text), 1, 0, Qt::AlignCenter);

     QWidget *widget = new QWidget;
     widget->setLayout(layout);

     return widget;
 }

 QWidget *MainWindow::createCellWidget(const QString &text,
                       DiagramItem::DiagramType type)
 {

     DiagramItem item(type, graphMenu);
     QIcon icon(item.image());

     QToolButton *button = new QToolButton;
     button->setIcon(icon);
     button->setIconSize(QSize(50, 50));
     button->setCheckable(true);
     buttonGroup->addButton(button, int(type));

     QGridLayout *layout = new QGridLayout;
     layout->addWidget(button, 0, 0, Qt::AlignHCenter);
     layout->addWidget(new QLabel(text), 1, 0, Qt::AlignCenter);

     QWidget *widget = new QWidget;
     widget->setLayout(layout);

     return widget;
 }

 QMenu *MainWindow::createColorMenu(const char *slot, QColor defaultColor)
 {
     QList<QColor> colors;
     colors << Qt::black << Qt::white << Qt::red << Qt::blue << Qt::yellow;
     QStringList names;
     names << tr("black") << tr("white") << tr("red") << tr("blue")
           << tr("yellow");

     QMenu *colorMenu = new QMenu;
     for (int i = 0; i < colors.count(); ++i) {
         QAction *action = new QAction(names.at(i), this);
         action->setData(colors.at(i));
         action->setIcon(createColorIcon(colors.at(i)));
         connect(action, SIGNAL(triggered()),
                 this, slot);
         colorMenu->addAction(action);
         if (colors.at(i) == defaultColor) {
             colorMenu->setDefaultAction(action);
         }
     }
     return colorMenu;
 }

 QIcon MainWindow::createColorToolButtonIcon(const QString &imageFile,
                         QColor color)
 {
     QPixmap pixmap(50, 80);
     pixmap.fill(Qt::transparent);
     QPainter painter(&pixmap);
     QPixmap image(imageFile);
     QRect target(0, 0, 50, 60);
     QRect source(0, 0, 42, 42);
     painter.fillRect(QRect(0, 60, 50, 80), color);
     painter.drawPixmap(target, image, source);

     return QIcon(pixmap);
 }

 QIcon MainWindow::createColorIcon(QColor color)
 {
     QPixmap pixmap(20, 20);
     QPainter painter(&pixmap);
     painter.setPen(Qt::NoPen);
     painter.fillRect(QRect(0, 0, 20, 20), color);

     return QIcon(pixmap);
 }
